#include <algorithm>
#include <iostream>
#include "../header/player.h"
#include "../header/skill.h"

using std::cout, std::endl, std::cin;

const General& Player::getGeneral() const {
    return general;
}

const Player& Player::setHp(int h) {
    hp = h;
}

int Player::getHp() const {
    return hp;
}

const Player& Player::setIdentity(Identity x) {
    identity = x;
    return *this;
}

Player::Identity Player::getIdentity() const {
    return identity;
}

const Player& Player::setAttack(Card* x) {
    attack = x;
    return *this;
}

const Card* Player::getAttack() const {
    return attack;
}

const Player& Player::setArmor(Card* x) {
    armor = x;
    return *this;
}

const Card* Player::getArmor() const {
    return armor;
}

const Player& Player::setPlusHorse(Card* x) {
    plusHorse = x;
    return *this;
}

const Card* Player::getPlusHorse() const {
    return plusHorse;
}

const Player& Player::setLessHorse(Card* x) {
    lessHorse = x;
    return *this;
}

const Card* Player::getLessHorse() const {
    return lessHorse;
}

const Player& Player::drawCards(const std::list<Card*>& x) {
    for (const auto &item : x) cards.push_back(item);
    return *this;
}

const std::list<Card*>& Player::getCards() const {
    return cards;
}

const Player& Player::addCard(Card* c) {
    cards.push_back(c);
    return *this;
}

const Player& Player::delCard(const std::list<Card*>::iterator& i) {
    cards.erase(i);
    return *this;
}

const Player& Player::delCard(Card* card) {
    cards.remove(card);
    return *this;
}

const Player& Player::pushTip(Card* c) {
    tips.push(c);
}
const Card* Player::popTip() {
    Card* c = tips.back();
    tips.pop();
    return c;
}

bool cardsByType(const std::list<Card*>& cards, Card::Type type) {
    return std::any_of(cards.begin(), cards.end(), [type](const Card& card){ return card.getType() == type; });
}

bool skillsByConvert(const std::vector<Skill*>& skills, Card::Type type) {
    return std::any_of(skills.begin(), skills.end(), [type](Skill* skill){ return skill->isConvert() == type; });
}

bool skillsByType(const std::vector<Skill*>& skills, Skill::Type type) {
    return std::any_of(skills.begin(), skills.end(), [type](Skill* skill){ return skill->getType(); });
}

void showCards(const std::list<Card*>& cards) {
    for(int i = 0; i < cards.size(); ++i) cout<<i<<"."<<cards.size()

}

Card* Player::enquirePlayCard(Card::Type type) {
    if(cardsByType(cards, type) || skillsByConvert(general.getSkills(), type)) {
        int id = 0;
        cout<<"请选择要出的牌的序号\n";
        cin>>id;
    }
    return nullptr;
}

const Player& Player::roundBefore(std::queue<Card*>& queue, std::queue<Card*>& heap, Player& nextPlay) {
    char opt{};
    while (!tips.empty()) {
        Card* c = tips.back();
        tips.pop();
        cout<<"【"<<general.getName()<<"】"<<"开始判定"<<"【"<<Card::getCardTypeStr(c->getType())<<"】";
        while (cardsByType(cards, Card::Type::NoSlack) || skillsByConvert(general.getSkills(), Card::Type::NoSlack)) {
            cout<<"是否无懈可击？（y/n）\n";
            if(cin.get() == 'n') break;
            if(Card* t = enquirePlayCard(Card::Type::NoSlack); t != nullptr) {
                delCard(t);
                heap.push(t);
//                if(skillsByType(cards, ))
            }
        }
//        switch (c->getType()) {
//            case Card::Type::NoThinking:
//        }
    }
    return *this;
}

const Player& Player::playCards() {
    return *this;
}

const Player& Player::roundAfter() {
    return *this;
}

bool Player::operator == (const Player &player) const {
    if(this == &player) return true;
}

bool Player::operator!=(const Player &player) const {
    return !(*this == player);
}

const Player& Player::setOver(bool o) {
    over = o;
    return *this;
}

bool Player::getOver() const {
    return over;
}

const Player &Player::ready() {
    for (const auto &item : general.findByStage(Skill::Stage::Ready)) item->exec();
    return determination();
}

Card* askForCards(Hand* hand, Card::Type type) {

}

const Player &Player::determination() {
    while (!tips.empty()) {
        Card*& card = tips.back();
        switch (card->getType()) {
            case Card::Type::NoThinking:
                for(const Player &player : hand->getPlayers()) {
                    player.
                }

        }
//        hand->
//        card->getType() == Card::Type::
    }
    return *this;
}

const Player &Player::setStageStatus(int x) {
    stageStatus = x;
    return *this;
}

const Player &Player::setStageStatus(Skill::Stage x) {
    stageStatus |= static_cast<int>(x);
}

int Player::getStageStatus() const {
    return stageStatus;
}

bool Player::isStageStatus(Skill::Stage x) const {
    return stageStatus & static_cast<int>(x);
}
